package utils

import (
	"context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/connectivity"
	"sync"
	grpc2 "gitee.com/zxs-micro/zxs-micro-common/grpc"
	"gitee.com/zxs-micro/zxs-micro-common/grpc/clients"
	"gitee.com/zxs-micro/zxs-micro-gateway/protos/gateway"
)

type CommonGatewayClient struct {
	c gateway.GatewayServiceClient
	clients.CommonClients
}

var cs = make(map[string]*CommonGatewayClient)
var clock sync.Mutex

func GenerateGatewayClients(addr string) (*CommonGatewayClient, error) {
	var err error
	clock.Lock()
	cli, ok := cs[addr]
	clock.Unlock()
	if !ok {
		cli = new(CommonGatewayClient)
		cli.ClientConn, err = grpc.Dial(addr, grpc2.GetClientDialOpts()...)
		if err != nil {
			return nil, err
		}
		cli.c = gateway.NewGatewayServiceClient(cli.ClientConn)
		cli.RemoteAddr = addr
		clock.Lock()
		cs[addr] = cli
		clock.Unlock()
	}
	return cli, nil
}

func (c *CommonGatewayClient) GatewayExec(params [][]byte, token, url string) ([]byte, error) {
	err := c.CheckConn()
	if err != nil {
		return nil, err
	}
	resp, err := c.c.LoadAndExec(context.Background(), &gateway.LoadExecRequest{
		Params:  params,
		Token:   token,
		ExecUrl: url,
	})
	if err != nil {
		return nil, err
	}
	return resp.Payload, err
}

func (c *CommonGatewayClient) CheckConn() (err error) {
	c.ClientLock.Lock()
	if c.ClientConn.GetState() == connectivity.Shutdown {
		c.ClientConn, err = grpc.Dial(c.RemoteAddr, grpc2.GetClientDialOpts()...)
		c.c = gateway.NewGatewayServiceClient(c.ClientConn)
	}
	c.ClientLock.Unlock()
	return
}

func (c *CommonGatewayClient) ShutdownClient() {
	c.ClientLock.Lock()
	c.ClientConn.Close()
	c.ClientLock.Unlock()
	clock.Lock()
	delete(cs, c.RemoteAddr)
	clock.Unlock()
}
